#include <iostream>
#include <algorithm>
#include <map> //用于离散化
using namespace std;

typedef struct CON
{
    int a;
    int b;
    bool e;
    bool operator<(struct CON w)
    {
        return e < w.e;
    }
    bool operator>(struct CON w)
    {
        return e > w.e;
    }
} con;

const int N = 100010;
const int M = 200010; //离散化的上限，也是并查集的大小

int n;
con a[N]; //条件要求
int p[M]; //并查集
int T;

bool cmp(con a, con b)
{
    return a > b;
}

int find(int x)
{
    if (p[x] == x)
        return x;
    return p[x] = find(p[x]);
}

int main()
{
    freopen("cin.txt", "r", stdin);
    cin >> T;
    while (T--)
    {
        map<int, int> m; //用于离散化
        int cnt = 0;     //现阶段分配到哪个数了
        cin >> n;
        for (int i = 0; i < n; ++i)
        {
            scanf("%d%d%d", &a[i].a, &a[i].b, &a[i].e);
            if (!m.count(a[i].a))  //判断当前输入的a是否出现过
                m[a[i].a] = cnt++; //给他分配个数
            if (!m.count(a[i].b))
                m[a[i].b] = cnt++;
        }
        for (int i = 0; i < cnt; ++i) //初始化并查集
            p[i] = i;
        sort(a, a + n, cmp); //排序后先处理冲突的
        int i;
        for (i = 0; i < n && a[i].e != 0; ++i) //处理相等的
        {
            int x = a[i].a, y = a[i].b; //初步提取出对应的数字
            x = m[x], y = m[y];         //找到自己被分配的数
            if (find(x) == find(y))     //本来就被判定相等了
                continue;               //那就不用合并了
            p[p[x]] = p[y];             //不然就合并一下
        }
        for (; i < n; ++i) //现在处理不等的情况
        {
            int x = a[i].a, y = a[i].b; //初步提取出对应的数字
            x = m[x], y = m[y];         //找到自己被分配的数
            if (find(x) == find(y))     //冲突了
            {
                puts("NO");
                break; //也没有继续下去的必要了
            }
        }
        if (i == n) //如果能够安全出来
            puts("YES");
    }
    return 0;
}